using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SilkSharp.src
{
	/*
	 * compute weighted quantization errors for LPC_order element input vectors, over one codebook stage.
	 * @author Dingxin Xu
	 */
	public class Silk_NLSF_VQ_sum_error_FLP
	{
		/*
		 * compute weighted quantization errors for LPC_order element input vectors, over one codebook stage.
		 * @param err Weighted quantization errors [ N * K ]
		 * @param _in Input vectors [ N * LPC_order ]
		 * @param w Weighting vectors [ N * LPC_order ]
		 * @param pCB Codebook vectors [ K * LPC_order ]
		 * @param N Number of input vectors
		 * @param K Number of codebook vectors
		 * @param LPC_order pCB
		 */
		static void SKP_Silk_NLSF_VQ_sum_error_FLP(
				  float[] err,               /* O    Weighted quantization errors [ N * K ]  */
			float[] _in,                /* I    Input vectors [ N * LPC_order ]         */
			float[] w,                 /* I    Weighting vectors [ N * LPC_order ]     */
			float[] pCB,               /* I    Codebook vectors [ K * LPC_order ]      */
			int N,                  /* I    Number of input vectors                 */
			int K,                  /* I    Number of codebook vectors              */
			int LPC_order           /* I    LPC order                               */
		)
		{
			int i, n;
			float diff, sum_error;
			float[] Wcpy = new float[ Silk_define.MAX_LPC_ORDER ];
			float[] cb_vec;
			int cb_vec_offset;

			/* Copy to local stack */
			System.Array.Copy( w, 0, Wcpy, 0, LPC_order );

			//TODO:
			float[] err_tmp = err;
			int err_tmp_offset = 0;
			float[] in_tmp = _in;
			int in_tmp_offset = 0;
			if( LPC_order == 16 )
			{
				/* Loop over input vectors */
				for( n = 0; n < N; n++ )
				{
					/* Loop over codebook */
					cb_vec = pCB;
					cb_vec_offset = 0;
					for( i = 0; i < K; i++ )
					{
						/* Compute weighted squared quantization error */
						diff = in_tmp[ in_tmp_offset + 0 ] - cb_vec[ cb_vec_offset + 0 ];
						sum_error = Wcpy[ 0 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 1 ] - cb_vec[ cb_vec_offset + 1 ];
						sum_error += Wcpy[ 1 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 2 ] - cb_vec[ cb_vec_offset + 2 ];
						sum_error += Wcpy[ 2 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 3 ] - cb_vec[ cb_vec_offset + 3 ];
						sum_error += Wcpy[ 3 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 4 ] - cb_vec[ cb_vec_offset + 4 ];
						sum_error += Wcpy[ 4 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 5 ] - cb_vec[ cb_vec_offset + 5 ];
						sum_error += Wcpy[ 5 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 6 ] - cb_vec[ cb_vec_offset + 6 ];
						sum_error += Wcpy[ 6 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 7 ] - cb_vec[ cb_vec_offset + 7 ];
						sum_error += Wcpy[ 7 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 8 ] - cb_vec[ cb_vec_offset + 8 ];
						sum_error += Wcpy[ 8 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 9 ] - cb_vec[ cb_vec_offset + 9 ];
						sum_error += Wcpy[ 9 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 10 ] - cb_vec[ cb_vec_offset + 10 ];
						sum_error += Wcpy[ 10 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 11 ] - cb_vec[ cb_vec_offset + 11 ];
						sum_error += Wcpy[ 11 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 12 ] - cb_vec[ cb_vec_offset + 12 ];
						sum_error += Wcpy[ 12 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 13 ] - cb_vec[ cb_vec_offset + 13 ];
						sum_error += Wcpy[ 13 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 14 ] - cb_vec[ cb_vec_offset + 14 ];
						sum_error += Wcpy[ 14 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 15 ] - cb_vec[ cb_vec_offset + 15 ];
						sum_error += Wcpy[ 15 ] * diff * diff;

						err_tmp[ err_tmp_offset + i ] = sum_error;
						cb_vec_offset += 16;
					}
					err_tmp_offset += K;
					in_tmp_offset += 16;
				}
			}
			else
			{
				//assert( LPC_order == 10 );

				/* Loop over input vectors */
				for( n = 0; n < N; n++ )
				{
					/* Loop over codebook */
					cb_vec = pCB;
					cb_vec_offset = 0;
					for( i = 0; i < K; i++ )
					{
						/* Compute weighted squared quantization error */
						diff = in_tmp[ in_tmp_offset + 0 ] - cb_vec[ cb_vec_offset + 0 ];
						sum_error = Wcpy[ 0 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 1 ] - cb_vec[ cb_vec_offset + 1 ];
						sum_error += Wcpy[ 1 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 2 ] - cb_vec[ cb_vec_offset + 2 ];
						sum_error += Wcpy[ 2 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 3 ] - cb_vec[ cb_vec_offset + 3 ];
						sum_error += Wcpy[ 3 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 4 ] - cb_vec[ cb_vec_offset + 4 ];
						sum_error += Wcpy[ 4 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 5 ] - cb_vec[ cb_vec_offset + 5 ];
						sum_error += Wcpy[ 5 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 6 ] - cb_vec[ cb_vec_offset + 6 ];
						sum_error += Wcpy[ 6 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 7 ] - cb_vec[ cb_vec_offset + 7 ];
						sum_error += Wcpy[ 7 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 8 ] - cb_vec[ cb_vec_offset + 8 ];
						sum_error += Wcpy[ 8 ] * diff * diff;
						diff = in_tmp[ in_tmp_offset + 9 ] - cb_vec[ cb_vec_offset + 9 ];
						sum_error += Wcpy[ 9 ] * diff * diff;

						err_tmp[ err_tmp_offset + i ] = sum_error;
						cb_vec_offset += 10;
					}
					err_tmp_offset += K;
					in_tmp_offset += 10;
				}
			}
		}
	}
}
